#ifndef RANGE_H
#define RANGE_H

#include <iostream>

class RangeIteratorException {
	friend std::ostream &operator <<(std::ostream &os, const RangeIteratorException &e);
public:
	RangeIteratorException(const std::string &message) : message(message) {}
private:
	std::string message;
};

class RangeIterator {
	friend std::ostream &operator <<(std::ostream &os, const RangeIterator &range);
public:
	RangeIterator(int beyondLast, int current, int step) : beyondLast(beyondLast), current(current), step(step) {}
	int &operator *();
	RangeIterator operator ++();
	bool operator ==(const RangeIterator &other) {return current == other.current && step == other.step;} 
	bool operator !=(const RangeIterator &other) {return !(*this == other);}
private:
	int first, beyondLast, current, step;
};

class Range {
	friend std::ostream &operator <<(std::ostream &os, const Range &range);
public:
	Range(int first, int last, int step=1) : first(first), last(last), step(step) {}
	Range(int last) : first(1), last(last), step(1) {}

	RangeIterator begin() {return RangeIterator(last+(step-(last-first)%step), first, step);}
	RangeIterator end() {return RangeIterator(last+(step-(last-first)%step), last+(step-(last-first)%step), step);}
private:
	int first, last, step;
};

#endif
